#define _WIN32_DCOM
#include <iostream.h>
#include <stdio.h>
#include <windows.h>
#include <ocidl.h>

{3AF0F8E7-ED16-11D2-BB52-006097B5EAFC}
const CLSID CLSID_PersistentVB = {0x3AF0F8E7, 0xED16, 0x11D2, {0xBB, 0x52, 0x00, 
  0x60, 0x97, 0xB5, 0xEA, 0xFC}};

class CPropertyBag : public IPropertyBag
{
public:
	// IUnknown
	ULONG __stdcall AddRef();
	ULONG __stdcall Release();
	HRESULT __stdcall QueryInterface(REFIID riid, void** ppv);

	// IPropertyBag
    HRESULT __stdcall Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog);
    HRESULT __stdcall Write(LPCOLESTR pszPropName, VARIANT* pVar);

	CPropertyBag() : m_cRef(1) { }

private:
	ULONG m_cRef;
};

HRESULT CPropertyBag::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog)
{
	cout << "READ" << endl;
	return S_OK;
}

HRESULT CPropertyBag::Write(LPCOLESTR pszPropName, VARIANT* pVar)
{
	wprintf(L"PropertyName = %s Value = %s\n", pszPropName, pVar->bstrVal);
	
	return S_OK;
}

ULONG CPropertyBag::AddRef()
{
	cout << "AddRef" << endl;
	return ++m_cRef;
}

ULONG CPropertyBag::Release()
{
	cout << "Release" << endl;
	if(--m_cRef != 0)
		return m_cRef;
	delete this;
	return 0;
}

HRESULT CPropertyBag::QueryInterface(REFIID riid, void** ppv)
{
	cout << "QueryInterface" << endl;
	if(riid == IID_IUnknown)
		*ppv = (IUnknown*)this;
	else if(riid == IID_IPropertyBag)
		*ppv = (IPropertyBag*)this;
	else 
	{
		*ppv = NULL;
		return E_NOINTERFACE;
	}
	AddRef();
	return S_OK;
}

void main()
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    if(FAILED(hr))
        cout << "CoInitializeEx failed. " << endl;

    IUnknown* pUnknown;
   hr = CoCreateInstance(CLSID_PersistentVB, NULL, CLSCTX_INPROC_SERVER, 
      IID_IUnknown, (void**)&pUnknown);
    if(FAILED(hr))
      cout << "CoCreateInstance failed. " << endl;

    IPersistStreamInit* pPersistStreamInit;
    hr = pUnknown->QueryInterface(IID_IPersistStreamInit, (void**)&pPersistStreamInit);
    if(FAILED(hr))
        cout << "IID_IPersistStreamInit not supported. " << endl;




    IPersistPropertyBag* pPersistPropertyBag;
    hr = pUnknown->QueryInterface(IID_IPersistPropertyBag, (void**)&pPersistPropertyBag);
    if(FAILED(hr))
        cout << "IID_IPersistPropertyBag not supported. " << endl;

	hr = pPersistPropertyBag->InitNew();
   if(FAILED(hr))
     printf("IPersistPropertyBag::InitNew failed %0x\n", hr);

	IPropertyBag* pPropertyBag = new CPropertyBag();

	hr = pPersistPropertyBag->Save(pPropertyBag, TRUE, TRUE);
   if(FAILED(hr))
     printf("IPersistPropertyBag::Save failed %0x\n", hr);





	IStream* pStream = 0;
	hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
    if(FAILED(hr))
        cout << "CreateStreamOnHGlobal failed. " << endl;

	cout << "About to InitNew" << endl;
	hr = pPersistStreamInit->InitNew();
   if(FAILED(hr))
     printf("IPersistStreamInit::InitNew failed %0x\n", hr);
	cout << "After InitNew" << endl;
	
/*
	hr = pPersistStreamInit->Save(pStream, FALSE);
   if(FAILED(hr))
     printf("IPersistStreamInit::Save failed %0x\n", hr);
*/



	IPersistStream* pPersistStream;
	pPersistStreamInit->QueryInterface(IID_IPersistStream, (void**)&pPersistStream);
   hr = OleSaveToStream(pPersistStream, pStream);
    if(FAILED(hr))
      cout << "OleSaveToStream failed. " << endl;


   LARGE_INTEGER zeroa = { 0, 0 };
   pStream->Seek(zeroa, STREAM_SEEK_SET, NULL);

   IUnknown* pObject;
   hr = OleLoadFromStream(pStream, IID_IUnknown, (void**)&pObject);
    if(FAILED(hr))
      cout << "OleLoadFromStream failed. " << endl;



   LARGE_INTEGER zero = { 0, 0 };
   pStream->Seek(zero, STREAM_SEEK_SET, NULL);


    IUnknown* pUnknown2;
   hr = CoCreateInstance(CLSID_PersistentVB, NULL, CLSCTX_INPROC_SERVER, 
      IID_IUnknown, (void**)&pUnknown2);
    if(FAILED(hr))
      cout << "CoCreateInstance failed. " << endl;

    IPersistStreamInit* pPersistStreamInit2;
    hr = pUnknown2->QueryInterface(IID_IPersistStreamInit, (void**)&pPersistStreamInit2);
    if(FAILED(hr))
        cout << "IID_IPersistStreamInit not supported. " << endl;

	hr = pPersistStreamInit2->Load(pStream);
    if(FAILED(hr))
       printf("IPersistStreamInit::Load failed %0x\n", hr);



//   zero.LowPart = 20;
  // pStream->Seek(zero, STREAM_SEEK_SET, NULL);

	void* data = GlobalAlloc(0, 500);
	ULONG count = 0;
	hr = pStream->Read(data, 50, &count);
  if(FAILED(hr))
    printf("IStream::Read failed %0x\n", hr);

	wprintf(L"count = %d, data = %s\n", count, data);

    pPersistStreamInit->Release();
	pStream->Release();
    pUnknown->Release();

    CoUninitialize();
}